package sysService

import (
	"context"
	"gitee.com/jokces/kit/enum"
	"gitee.com/jokces/kit/errc"
	sysModel "gitee.com/jokces/kit/global/admin/model"
	"gitee.com/jokces/kit/typ"
	"gitee.com/jokces/kit/util/icopier"
	"time"
)

func (svc *Service) AddClient(ctx context.Context, in *sysModel.OauthClientAddReq) error {
	do := &sysModel.SysOauthClient{}
	if err := icopier.CopyWithOption(do, in, icopier.Option{
		IgnoreEmpty: true,
		DeepCopy:    false,
	}); err != nil {
		return err
	}
	if exist, _, err := svc.d.ClientOne(ctx, &sysModel.SysOauthClient{
		ClientId: in.ClientId,
	}); err != nil {
		return err
	} else if exist {
		return errc.ErrParamInvalid.MultiMsg("客户端ID已存在")
	}

	//创建秘钥,这里暂时使用的ID，做为秘钥
	if in.ClientSecret == "" {
		in.ClientSecret = in.ClientId
	}

	if err := svc.d.GetDao().TxInsert(nil, do); err != nil {
		return err
	}
	return nil
}
func (svc *Service) UpdateClient(ctx context.Context, in *sysModel.OauthClientUpdateReq) error {
	if exist, _, err := svc.d.ClientOne(ctx, &sysModel.SysOauthClient{
		Id: in.Id,
	}); err != nil {
		return err
	} else if !exist {
		return errc.ErrParamInvalid.MultiMsg("客户端不存在")
	}
	do := &sysModel.SysOauthClient{}
	if err := icopier.CopyWithOption(do, in, icopier.Option{
		IgnoreEmpty: true,
		DeepCopy:    false,
	}); err != nil {
		return err
	}
	if err := svc.d.GetDao().TxBeanUpdate(nil, do.Id, do); err != nil {
		return err
	}
	return nil
}
func (svc *Service) DelClient(ctx context.Context, id int64) error {
	exist, c, err := svc.d.ClientOne(ctx, &sysModel.SysOauthClient{
		Id: id,
	})
	if err != nil {
		return err
	}
	if !exist {
		return errc.ErrParamInvalid.MultiMsg("客户端不存在")
	}
	if cacheErr := svc.r.DelCache()(ctx, &sysModel.CacheClient{ClientId: c.ClientId}, func(ctx context.Context, in interface{}) error {
		if err := svc.d.GetDao().TxUpdate(nil, id, &sysModel.SysOauthClient{
			IsDel: enum.DEL,
		}, []string{"is_del"}); err != nil {
			return err
		}
		return nil
	}); cacheErr != nil {
		return cacheErr
	}
	return nil
}
func (svc *Service) QueryClientList(ctx context.Context, in *sysModel.OauthQueryReq) (typ.ListResp, error) {
	rs := typ.ListResp{}
	count, clients, err := svc.d.ClientList(ctx, &sysModel.SysOauthClient{
		ClientId:   in.ClientId,
		ClientName: in.ClientName,
	}, in.PageReq)
	if err != nil {
		return rs, err
	}
	if in.PageReq == nil {
		list := make([]*sysModel.OauthQueryResp, 0)
		for _, client := range clients {
			list = append(list, &sysModel.OauthQueryResp{
				ClientName: client.ClientId,
				ClientId:   client.ClientName,
			})
		}
		rs.List = list
	} else {
		rs.List = clients
	}
	rs.Count = count
	return rs, nil
}
func (svc *Service) ClientById(ctx context.Context, clientId string) (*sysModel.SysOauthClient, error) {
	exist, client, err := svc.d.ClientOne(ctx, &sysModel.SysOauthClient{
		ClientId: clientId,
	})
	if err != nil {
		return nil, err
	}
	if exist {
		return client, nil
	}
	return nil, nil
}
func (svc *Service) ClientResource(ctx context.Context, req *sysModel.ClientAddResourceReq) error {
	exist, cli, err := svc.d.ClientOne(ctx, &sysModel.SysOauthClient{
		Id: req.Id,
	})
	if err != nil {
		return err
	}
	if !exist {
		return errc.ErrParamInvalid.MultiMsg("客户端不存在")
	}
	if exist, _, err := svc.d.DicOne(ctx, &sysModel.SysDic{
		Key: req.ResourceIds,
	}); err != nil {
		return err
	} else if !exist {
		return errc.ErrParamInvalid.MultiMsg("资源不存在")
	}
	if err := svc.d.GetDao().TxUpdate(nil, cli.Id, &sysModel.SysOauthClient{
		ResourceIds: req.ResourceIds,
	}, []string{"resource_ids"}); err != nil {
		return err
	}
	return nil
}

// RedisClientById 从缓存中获取对应的客户端
func (svc *Service) RedisClientById(ctx context.Context, clientId string) (*sysModel.SysOauthClient, error) {
	in := &sysModel.CacheClient{ClientId: clientId}
	cli := &sysModel.SysOauthClient{}
	rs, err := svc.r.KeyWithCache(12*time.Hour, cli)(ctx, in.Key(), func() (interface{}, error) {
		return svc.ClientById(ctx, in.ClientId)
	})
	if err != nil {
		return cli, err
	}
	return rs.(*sysModel.SysOauthClient), nil
}

// RedisUpDateClient 更新对应的缓存
func (svc *Service) RedisUpDateClient(ctx context.Context, in *sysModel.OauthClientUpdateReq) error {
	if cacheErr := svc.r.DelCache()(ctx, in, func(ctx context.Context, in interface{}) error {
		if err := svc.UpdateClient(ctx, in.(*sysModel.OauthClientUpdateReq)); err != nil {
			return err
		}
		return nil
	}); cacheErr != nil {
		return cacheErr
	}
	return nil
}
